//Copyright (c) Microsoft Corporation.  All rights reserved.

using System;
using System.Text;
using System.Collections.Generic;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Eas.WebCrawler.Interfaces;

namespace Eas.WebCrawler.Test.PlugIns {
    /// <summary>
    /// Summary description for SelectorTest
    /// </summary>
    [TestClass]
    public class SelectorTest {
        static Eas.WebCrawler.PlugIns.Selectors.ConstantSelector FalseSelector = new Eas.WebCrawler.PlugIns.Selectors.ConstantSelector(false);
        static Eas.WebCrawler.PlugIns.Selectors.ConstantSelector TrueSelector = new Eas.WebCrawler.PlugIns.Selectors.ConstantSelector(true);
        static Eas.WebCrawler.PlugIns.Selectors.MaximumDepthSelector Depth1Selector = new Eas.WebCrawler.PlugIns.Selectors.MaximumDepthSelector(1, TrueSelector);
        static Eas.WebCrawler.PlugIns.Selectors.ConditionalSelector GoogleSelector = new Eas.WebCrawler.PlugIns.Selectors.ConditionalSelector(TrueSelector, FalseSelector, delegate(Request request) { return request.Uri.Host == "www.google.com"; });


        static string[] aspnet = new string[] { "aspx", "asmx" };
        static string[] html = new string[] { "htm", "html" };
        static string[] googleNames = new string[] { "Google", "froogle" };

        static Eas.WebCrawler.PlugIns.Selectors.ExtensionSelector aspnetSelector = new Eas.WebCrawler.PlugIns.Selectors.ExtensionSelector(TrueSelector, FalseSelector, false, aspnet);
        static Eas.WebCrawler.PlugIns.Selectors.ExtensionSelector htmlSelector = new Eas.WebCrawler.PlugIns.Selectors.ExtensionSelector(TrueSelector, FalseSelector, true, html);
        static Eas.WebCrawler.PlugIns.Selectors.NameSelector nameSelector = new Eas.WebCrawler.PlugIns.Selectors.NameSelector(TrueSelector, FalseSelector, googleNames);

        public SelectorTest() {
            //
            // TODO: Add constructor logic here
            //
        }

        #region Additional test attributes
        //
        // You can use the following additional attributes as you write your tests:
        //
        // Use ClassInitialize to run code before running the first test in the class
        // [ClassInitialize()]
        // public static void MyClassInitialize(TestContext testContext) { }
        //
        // Use ClassCleanup to run code after all tests in a class have run
        // [ClassCleanup()]
        // public static void MyClassCleanup() { }
        //
        // Use TestInitialize to run code before running each test 
        // [TestInitialize()]
        // public void MyTestInitialize() { }
        //
        // Use TestCleanup to run code after each test has run
        // [TestCleanup()]
        // public void MyTestCleanup() { }
        //
        #endregion

        [TestMethod]
        /// <summary>Executes the SimpleConstantSelectorTest test.</summary>
        public void SimpleConstantSelectorTest() {
            Assert.IsTrue(TrueSelector.ShouldFollow(RequestHelper.rGoogle));
            Assert.IsFalse(FalseSelector.ShouldFollow(RequestHelper.rGoogle));
            Assert.IsFalse(FalseSelector.Value);
        }

        [TestMethod]
        /// <summary>Executes the TestDepthSelector test.</summary>
        public void TestDepthSelector() {
            using (NMock2.Mockery mock = new NMock2.Mockery()) {
                WebCrawlerContext context = mock.NewMock<WebCrawlerContext>();
                Depth1Selector.Initialize(context);
                Assert.IsTrue(Depth1Selector.ShouldFollow(RequestHelper.rGoogle));
                Assert.IsTrue(Depth1Selector.ShouldFollow(RequestHelper.rPartial));
                Assert.IsTrue(Depth1Selector.ShouldFollow(RequestHelper.rDeepPartial));
                Assert.IsFalse(Depth1Selector.ShouldFollow(RequestHelper.r2Deep));
                Assert.IsFalse(Depth1Selector.ShouldFollow(RequestHelper.r3Deep));
                Assert.IsFalse(Depth1Selector.ShouldFollow(RequestHelper.r4Deep));
                Assert.AreSame(Depth1Selector.InnerSelector, TrueSelector);
                Assert.AreEqual<int>(1, Depth1Selector.MaximumDepth);
                mock.VerifyAllExpectationsHaveBeenMet();
            }
        }

        [TestMethod]
        /// <summary>Executes the ConditionalSelectorTest test.</summary>
        public void ConditionalSelectorTest() {
            Assert.AreSame(TrueSelector, GoogleSelector.TrueSelector);
            Assert.AreSame(FalseSelector, GoogleSelector.FalseSelector);
            Assert.IsTrue(GoogleSelector.ShouldFollow(RequestHelper.rPartial));
            Assert.IsFalse(GoogleSelector.ShouldFollow(RequestHelper.rYahoo));
        }

        [TestMethod]
        /// <summary>Executes the TestExtensionSelector test.</summary>
        public void TestExtensionSelector() {
            using (NMock2.Mockery mock = new NMock2.Mockery()) {
                WebCrawlerContext context = mock.NewMock<WebCrawlerContext>();
                htmlSelector.Initialize(context);
                Assert.IsTrue(htmlSelector.ShouldFollow(RequestHelper.rHtmlRef));
                Assert.IsTrue(htmlSelector.ShouldFollow(RequestHelper.rGoogle));
                Assert.IsFalse(htmlSelector.ShouldFollow(RequestHelper.rPhpRef));
                Assert.IsTrue(aspnetSelector.ShouldFollow(RequestHelper.rPartial));
                Assert.IsFalse(aspnetSelector.ShouldFollow(RequestHelper.rGoogle));
                Assert.IsFalse(aspnetSelector.ShouldFollow(RequestHelper.rPhpRef));
                Assert.IsTrue(aspnetSelector.ShouldFollow(RequestHelper.rMixedCaseAspNet));
                Assert.AreEqual<int>(aspnet.Length, aspnetSelector.FollowedExtensions.Length);
                mock.VerifyAllExpectationsHaveBeenMet();
            }
        }

        [TestMethod]
        /// <summary>Executes the TestNameSelector test.</summary>
        public void TestNameSelector() {
            List<string> googleNamesList = new List<string>();
            googleNamesList.AddRange(nameSelector.Names);
            Assert.AreEqual<int>(googleNames.Length, googleNamesList.Count);
            Assert.IsFalse(nameSelector.ShouldFollow(RequestHelper.rMicrosoft));
            Assert.IsTrue(nameSelector.ShouldFollow(RequestHelper.rGoogle));
            Assert.IsTrue(nameSelector.ShouldFollow(RequestHelper.rMixedCaseFroogle));
            Assert.IsTrue(nameSelector.ShouldFollow(RequestHelper.rMixedCaseAspNet));
            Assert.IsFalse(nameSelector.ShouldFollow(RequestHelper.r4Deep));
        }

        [TestMethod]
        /// <summary>Executes the TestStayOnHostSelector test.</summary>
        public void TestStayOnHostSelector() {
            Eas.WebCrawler.PlugIns.Selectors.StayOnHostSelector selector = new Eas.WebCrawler.PlugIns.Selectors.StayOnHostSelector(TrueSelector, FalseSelector);
            Assert.IsTrue(selector.ShouldFollow(RequestHelper.rGoogle));
            Assert.IsTrue(selector.ShouldFollow(RequestHelper.rPartial));
            Assert.IsFalse(selector.ShouldFollow(new Request(UriHelper.Yahoo, RequestHelper.rGoogle)));
        }

        [TestMethod]
        /// <summary>Executes the TestExtensionSelectorForDefaultDirectory test.</summary>
        public void TestExtensionSelectorForDefaultDirectory() {
            using (NMock2.Mockery mock = new NMock2.Mockery()) {
                WebCrawlerContext context = mock.NewMock<WebCrawlerContext>();
                Eas.WebCrawler.PlugIns.Selectors.ExtensionSelector selector = new Eas.WebCrawler.PlugIns.Selectors.ExtensionSelector(TrueSelector, FalseSelector, true, Eas.WebCrawler.PlugIns.Selectors.ExtensionSelector.HtmlExtensions);
                Assert.IsTrue(selector.UseTrueSelectorForDirectoryUris);
                Assert.IsTrue(selector.ShouldFollow(new Request("http://www.google.com")));
                mock.VerifyAllExpectationsHaveBeenMet();
            }
        }

        [TestMethod]
        /// <summary>Executes the TestFalseExtensionSelectorForDefaultDirectory test.</summary>
        public void TestFalseExtensionSelectorForDefaultDirectory() {
            using (NMock2.Mockery mock = new NMock2.Mockery()) {
                WebCrawlerContext context = mock.NewMock<WebCrawlerContext>();
                Eas.WebCrawler.PlugIns.Selectors.ExtensionSelector selector = new Eas.WebCrawler.PlugIns.Selectors.ExtensionSelector(TrueSelector, FalseSelector, false, Eas.WebCrawler.PlugIns.Selectors.ExtensionSelector.HtmlExtensions);
                Assert.IsFalse(selector.UseTrueSelectorForDirectoryUris);
                Assert.IsFalse(selector.ShouldFollow(new Request("http://www.google.com")));
                mock.VerifyAllExpectationsHaveBeenMet();
            }
        }

        [TestMethod]
        /// <summary>Executes the TestDefaultHandlingWithComplicatedUris test.</summary>
        public void TestDefaultHandlingWithComplicatedUris() {
            using (NMock2.Mockery mock = new NMock2.Mockery()) {
                WebCrawlerContext context = mock.NewMock<WebCrawlerContext>();
                Eas.WebCrawler.PlugIns.Selectors.ExtensionSelector trueSelector = new Eas.WebCrawler.PlugIns.Selectors.ExtensionSelector(TrueSelector, FalseSelector, true, Eas.WebCrawler.PlugIns.Selectors.ExtensionSelector.HtmlExtensions);
                Eas.WebCrawler.PlugIns.Selectors.ExtensionSelector falseSelector = new Eas.WebCrawler.PlugIns.Selectors.ExtensionSelector(TrueSelector, FalseSelector, false, Eas.WebCrawler.PlugIns.Selectors.ExtensionSelector.HtmlExtensions);
                Assert.IsTrue(trueSelector.ShouldFollow(new Request("http://www.google.com?sss=gggg")));
                Assert.IsFalse(falseSelector.ShouldFollow(new Request("http://www.google.com?sss=gggg")));
                mock.VerifyAllExpectationsHaveBeenMet();
            }
        }

        [TestMethod]
        /// <summary>Executes the HandleCompositeArrays test.</summary>
        public void HandleCompositeArrays() {
            using (NMock2.Mockery mock = new NMock2.Mockery()) {
                WebCrawlerContext context = mock.NewMock<WebCrawlerContext>();
                Eas.WebCrawler.PlugIns.Selectors.ExtensionSelector selector = new Eas.WebCrawler.PlugIns.Selectors.ExtensionSelector(TrueSelector, FalseSelector, true, Eas.WebCrawler.PlugIns.Selectors.ExtensionSelector.HtmlExtensions, Eas.WebCrawler.PlugIns.Selectors.ExtensionSelector.FlashExtensions);
                Assert.IsTrue(selector.ShouldFollow(new Request("http://www.google.com/aaa.html")));
                Assert.IsTrue(selector.ShouldFollow(new Request("http://www.google.com/aaa.swf")));
                mock.VerifyAllExpectationsHaveBeenMet();
            }
        }

        [TestMethod]
        /// <summary>Executes the HandleComplicatedUrisInExtensionSelctor test.</summary>
        public void HandleComplicatedUrisInExtensionSelctor() {
            using (NMock2.Mockery mock = new NMock2.Mockery()) {
                WebCrawlerContext context = mock.NewMock<WebCrawlerContext>();
                Eas.WebCrawler.PlugIns.Selectors.ExtensionSelector selector = new Eas.WebCrawler.PlugIns.Selectors.ExtensionSelector(TrueSelector, FalseSelector, true, Eas.WebCrawler.PlugIns.Selectors.ExtensionSelector.HtmlExtensions);
                Assert.IsTrue(selector.ShouldFollow(new Request("http://www.google.com/aaa.html?sss=wwww")));
                Assert.IsTrue(selector.ShouldFollow(new Request("http://www.google.com/aaa.html/sss=wwww")));//We cant handle these paths, treated as a dir

                Assert.IsFalse(selector.ShouldFollow(new Request("http://www.google.com/aaa.js?sss=wwww")));
                Assert.IsTrue(selector.ShouldFollow(new Request("http://www.google.com/aaa.js/sss=wwww")));//We cant handle these paths, treated as a dir
                mock.VerifyAllExpectationsHaveBeenMet();
            }
        }

    }
}
